﻿#define _CRT_SECURE_NO_WARNINGS 1

//#include"process.h"
//// 倒计时程序
//void end_time()
//{
//	int i = 10;
//	while (i >= 0)
//	{
//		printf("%-2d\r", i); // \n                                                                          
//
//		fflush(stdout);
//		i--;
//		Sleep(1000);
//	}
//	printf("\n");
//}
//// 简单进度条程序
//void DownLoad()
//{
//	double total = 1024.0;
//	double speed = 1.0;
//	double current = 0;
//	while (current <= total)
//	{
//		FlushProcess(total, current);
//		// 下载代码
//		Sleep(3000); // 充当下载数据
//		current += speed;
//	}
//	printf("\ndownload %.2lfMB Done\n", current);
//}
//
//int main()
//{
//	//end_time();
//	DownLoad();
//	return 0;
//}
//#include <stdio.h>
//#include <sys/types.h>
//#include <unistd.h>
//// 2. 创建进程，并查看
//int main()
//{
//	int ret = fork();
//	printf("我是一个进程，我的pid是：%d！，我的返回值是：%d\n", getpid(), ret);
//	return 0;
//}
//int main()
//{
//	int ret = fork();
//	if (ret < 0) {
//		perror("创建进程失败");
//		return 1;
//	}
//	else if (ret == 0) { //child
//		while (1)
//		{
//			sleep(1);
//			printf("I am child : %d!, ret: %d\n", getpid(), ret);
//		}
//
//	}
//	else { //father
//		while (1)
//		{
//			sleep(1);
//			printf("I am father : %d!, ret: %d\n", getpid(), ret);
//		}
//	}
//	return 0;
//}int main()
//{
//	int ret = fork();
//	if (ret < 0) {
//		perror("创建进程失败");
//		return 1;
//	}
//	else if (ret == 0) { //child
//		while (1)
//		{
//			sleep(1);
//			printf("I am child : %d!, ret: %d\n", getpid(), ret);
//		}
//
//	}
//	else { //father
//		while (1)
//		{
//			sleep(1);
//			printf("I am father : %d!, ret: %d\n", getpid(), ret);
//		}
//	}
//	return 0;
//}
//#include<iostream>
//using namespace std;
//int sum(int n)
//{
//    int s = 0;
//    while (n >0)
//    {
//        s += (n % 10) * (n % 10);
//        n /= 10;
//    }
//    return s;
//}
//bool isHappy(int n) {
//    int x = n;
//    int y = n;
//    while (1)
//    {
//        x = sum(x);
//        y = sum(y);
//        y = sum(y);
//        if (x == y) break;
//    }
//    return x == 1;
//}
//int main()
//{
//    cout << isHappy(19) << endl;
//    return 0;
//}
#include <iostream>
#include<vector>
using namespace std;
//int main()
//{
//    int N = 0, K = 0, count = 0;
//    cin >> N >> K;
//    vector<int> input(N);
//    for (int i = 0; i < N; i++) cin >> input[i];
//    for (int i = 0; i < N; i++)
//    {
//        int sum = 0;
//        for (int j = i; j < N; j++)
//        {
//            sum += input[j];
//            if (sum % K == 0) ++count;
//        }
//    }
//    cout << count << endl;
//    return 0;
//}

// 1. 测试命令行参数
#include <stdio.h>
#include <string.h>
//int main(int agrc, char* argv[])
//{
//	if (agrc != 2)
//	{
//		printf("hello world!\n");
//		printf("注：这是单纯的无选项功能，更多选项用法：./test [-a][-b][-c]\n");
//		return 0;
//	}
//	char* tmp = argv[1];
//	if (strcmp(tmp, "-a") == 0)
//		printf("hello world -a\n");
//	else if (strcmp(tmp, "-b") == 0)
//		printf("hello world -b\n");
//	else if (strcmp(tmp, "-c") == 0)
//		printf("hello world -c\n");
//	else
//		printf("目前无该选项功能，还在开发中…… 更多选项用法：./test [-a][-b][-c]\n");
//	return 0;
//}
// 2. 测试命令行参数表
//int main(int agrc, char* argv[])
//{
//	for (int i = 0; i < agrc; i++)
//	{
//		printf("argv[%d]:%s\n", i, argv[i]);
//	}
//}

// 3. 获取环境变量的代码方法
// (1).
//int main(int argc, char* argv[], char* env[])
//{
//	for (int i = 0; env[i]; i++)
//	{
//		printf("env[%d]:%s\n", i, env[i]);
//	}
//	return 0;
//}
// (2).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//int main()
//{
//	char* shuaiming = getenv("USER");
//	if (strcmp(shuaiming, "shuaiming") == 0)
//	{
//		printf("这是shuaiming专属执行代码！\n");
//	}
//	else
//	{
//		printf("不是牢弟，你是shuaiming吗，你直接给我坐下！\n");
//	}
//	return 0;
//}
//(3).extern char **environ
//extern char** environ;
//int main(int argc, char* argv[])
//{
//    for (int i = 0; environ[i]; i++)
//    {
//        printf("environ[%d]-> %s\n", i, environ[i]);
//    }
//}
// 2. 验证虚拟地址
//#include <stdio.h>
//#include <stdlib.h>
//int g_val = 0;
//int main()
//{
//	pid_t id = fork();
//	if (id < 0) {
//		perror("fork");
//		return 0;
//	}
//	else if (id == 0) { //child
//		printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);
//	}
//	else { //parent
//		printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
//	}
//	return 0;
//}
//#include <stdio.h>
//#include <unistd.h>
//#include <stdlib.h>
//int g_val = 0;
//int main()
//{
//	pid_t id = fork();
//	if (id < 0) {
//		perror("fork");
//		return 0;
//	}
//	else if (id == 0) { //child,子进程肯定先跑完，也就是子进程先修改，完成之后，父进程再读取
//			g_val = 100;
//		printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);
//	}
//	else { //parent
//		sleep(3);
//		printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
//	}
//	sleep(1);
//	return 0;
//}
//struct task_struct
//{
//	/*...*/
//	struct mm_struct* mm; /* 对于普通的用户进程来说该字段指向他的
//	虚拟地址空间的用户空间部分，对于内核线程来说这部分为NULL。*/
//	struct mm_struct* active_mm; /* 该字段是内核线程使用的。当该
//	进程是内核线程时，它的mm字段为NULL，表示没有内存地址空间，可也并不是真正的没有，这是因为所
//	有进程关于内核的映射都是一样的，内核线程可以使用任意进程的地址空间。*/
//	/*...*/
//};
//struct mm_struct
//{
//	/*...*/
//	struct vm_area_struct* mmap; /* 指向虚拟区间(VMA)链表 */
//	struct rb_root mm_rb; /* red_black树 */
//	unsigned long task_size; /*具有该结构体的进程的虚拟地址空间的⼤⼩*/
//	/*...*/
//	// 代码段、数据段、堆栈段、参数段及环境段的起始和结束地址。 
//	unsigned long start_code, end_code, start_data, end_data;
//	unsigned long start_brk, brk, start_stack, end_stack;
//	unsigned long arg_start, arg_end, env_start, env_end;
//	/*...*/
//};
//struct vm_area_struct {
//	unsigned long vm_start; //虚存区起始 
//	unsigned long vm_end; //虚存区结束 
//	struct vm_area_struct* vm_next, * vm_prev; //前后指针 
//	struct rb_node vm_rb; //红⿊树中的位置 
//	unsigned long rb_subtree_gap;
//	struct mm_struct* vm_mm; //所属的 mm_struct 
//	pgprot_t vm_page_prot;
//	unsigned long vm_flags; //标志位 
//	struct {
//		struct rb_node rb;
//		unsigned long rb_subtree_last;
//	} shared;
//	struct list_head anon_vma_chain;
//	struct anon_vma* anon_vma;
//	const struct vm_operations_struct* vm_ops; //vma对应的实际操作 
//	unsigned long vm_pgoff; //⽂件映射偏移量 
//	struct file* vm_file; //映射的⽂件 
//	void* vm_private_data; //私有数据 
//	atomic_long_t swap_readahead_info;
//#ifndef CONFIG_MMU
//	struct vm_region* vm_region; /* NOMMU mapping region */
//#endif
//#ifdef CONFIG_NUMA
//	struct mempolicy* vm_policy; /* NUMA policy for the VMA */
//#endif
//	struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
//} __randomize_layout;
//#include <stdio.h>
//int main()
//{
//	printf("Hello world\n");
//	printf("%s\n", strerror(0));
//	return 0;
//}
int main()
{
	//int a = 1 / 0;
	//printf("%s\n", strerror(1));
	//exit(-1);
	return 0;
}
#include <unistd.h>
void _exit(int status);
int main()
{
	_exit(-1);
	return 0;
}
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main()
{
	printf("小美同意了小帅的约会请求，先让小帅在8号楼下等她化妆\n");
	printf("此时小帅知道了小美同意了他的请求，来到了8号楼下进行等待...\n");
	int ret = fork();
	if (ret == 0)
	{
		// child
		printf("小美正在化妆中\n");
		int n = 10;
		while (n--)
		{
			printf("小美化妆还有%d分钟\n", n);
			sleep(1);
		}
	}
	waitpid(-1, NULL, 0);// 阻塞等待
	printf("小帅一直在等待小美\n");
	printf("最后等待成功，与小美一同约会去了\n");
	return 0;
}
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
// 2. 非阻塞等待
int main()
{
	printf("小美同意了小帅的约会请求，先让小帅在8号楼下等她化妆\n");
	int ret = fork();
	if (ret == 0)
	{
		// child 
		printf("小美正在化妆中...\n");
		int n = 10;
		while (n--)
		{
			printf("小美化妆还有%d分钟\n", n);
			sleep(1);
		}
		exit(0);
	}
	pid_t pid = 0;
	printf("小帅先去买了奶茶\n");
	do {
		pid = waitpid(-1, NULL, WNOHANG); // 非阻塞轮询，没等待子进程退出就返回0，等到子进程退出返回子进程pid
		if (pid == 0)
		{
			sleep(2);
			printf("小帅然后来到了8号楼下，一边等待小美，一边苦学高情商技巧...\n");
		}

	} while (pid == 0);
	printf("小美正在下楼...\n");
	printf("小帅等到了小美，与小美开心的约会去了\n");
	return 0;
}

#include <unistd.h>
int main()
{
    char* const argv[] = { "ps", "-ef", NULL };
	char* const envp[] = { "PATH=/bin:/usr/bin", "TERM=console", NULL };
	execl("/bin/ps", "ps", "-ef", NULL);
	// 带p的，可以使⽤环境变量PATH，⽆需写全路径 
	execlp("ps", "ps", "-ef", NULL);
	// 带e的，需要⾃⼰组装环境变量 
	execle("ps", "ps", "-ef", NULL, envp);
	execv("/bin/ps", argv);

	// 带p的，可以使⽤环境变量PATH，⽆需写全路径 
	execvp("ps", argv);
	// 带e的，需要⾃⼰组装环境变量 
	execve("/bin/ps", argv, envp);
	return 0;
}
int main()
{
	printf("我的程序要运行了！\n");
	// 无环境变量PATH，需写全路径                                                                  
	execl("/bin/ls", "ls", "-l", NULL);
	printf("我的程序结束了!\n");
	exit(0);
}
int main()
{
	printf("我的程序要运行了！\n");
	// 有环境变量PATH，不需写全路径                                                    
	execlp("ls", "ls", "-l", NULL);
	printf("我的程序结束了!\n");
	exit(0);
	return 0;
}
int main()
{
	printf("我的程序要运行了！\n");
	// 自己组装的命令行参数表与环境变量表都是要以NULL结尾
	char* const argv[] = { "ls", "-l","-a", NULL };
	char* const envp[] = { "PATH=/bin:/usr/bin", NULL };
	// 需写全路径                                                                                                                                      
	execve("/bin/ls", argv, envp);
	printf("我的程序结束了!\n");
	return 0;
}
int main()
{
	printf("我的程序要运行了！\n");
	execl("/usr/bin/python3", "python", "hello.py", NULL);
	printf("hello C\n");
	printf("我的程序结束了!\n");
}
#include <stdio.h>
int main()
{
	FILE* fp = fopen("hello.txt", "w");
	if (!fp)
		perror("fopen error!");
	while (1);
	fclose(fp);
	return 0;
}
#include <stdio.h>
#include <string.h>
int main()
{
	FILE* fp = fopen("hello.txt", "w");
	if (!fp)
	{
		perror("fopen error");
		return 1;
	}
	const char* msg = "我是小帅，喜欢小美!\n";
	int count = 5; // 准备写入5次
	while (count--)
		fwrite(msg, strlen(msg), 1, fp);
	fclose(fp);
	return 0;
}
#include <stdio.h>
#include <string.h>
// 3. 读文件
int main()
{
	// 以读的方式打开，若不存在，则新建，存在则从头开始读，不会刷新内容
	FILE* fp = fopen("hello.txt", "r");
	if (!fp)
	{
		perror("fopen error!");
		return 1;
	}
	char buf[1024]; // 定义缓冲区来读
	const char* msg = "我是小帅，喜欢小美!\n";
	while (1)
	{
		ssize_t s = fread(buf, 1, strlen(msg), fp);
		if (s > 0)
		{
			buf[s] = 0; // 文件里读进来没有\0，\0是语言层面的规定，所以需要自己读入后，手动增添\0
			printf("%s", buf);
		}
		if (feof(fp))
			break;
	}
	fclose(fp);
	return 0;
}
#include <stdio.h>
#include <string.h>
// 4. 实现自己的cat命令
int main(int argc, char* argv[])
{
	if (argc != 2)
	{
		printf("error，使用cat命令必须后面接要打印的内容！\n");
		return 1;
	}
	FILE* fp = fopen(argv[1], "r");
	if (!fp)
	{
		perror("fopen error!\n");
		return 1;
	}
	char buf[1024]; // 定义缓冲区
	while (1)
	{
		int size = fread(buf, 1, sizeof(buf), fp);
		if (size > 0)
		{
			buf[size] = 0;
			printf("%s", buf);
		}
		if (feof(fp))
			break;
	}
	fclose(fp);
	return 0;
}
int main()
{
	// 1. printf
	printf("hello printf\n");
	// 2. fprintf
	fprintf(stdout, "hello fprintf\n");
	// 3. fwrite                                                                                                                                                                
	const char* msg = "hello fwrite\n";
	fwrite(msg, strlen(msg), 1, stdout);
	return 0;
}

#include <stdio.h>
#include <string.h>
int main()
{
	// 1. printf
	printf("hello printf\n");
	// 2. fprintf
	fprintf(stdout, "hello fprintf\n");
	// 3. fwrite
	const char* msg = "hello fwrite\n";
	fwrite(msg, strlen(msg), 1, stdout);
	return 0;
}
#include <stdio.h>
#define ONE 1  // 0000 0001
#define TWO 2  // 0000 0010
#define THREE 4// 0000 0100
void func(int flag)
{
	if (flag & ONE) printf("has ONE  ");
	if (flag & TWO) printf("has TWO  ");
	if (flag & THREE) printf("has THREE  ");
	printf("\n");
}
int main()
{
	printf("第一次调用：---------------\n");
	func(ONE);
	printf("第二次调用：---------------\n");
	func(ONE | TWO);
	printf("第三次调用：---------------\n");
	func(ONE | TWO | THREE);
	return 0;
}
// 7. 采用系统调用的方式写文件 
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
	umask(0); // 自己设置掩码
	// 没有该文件，采用三个参数的open先创建文件，第三个参数是对应的权限码
	int fd = open("shuai.txt", O_CREAT | O_WRONLY, 0644);
	if (fd < 0)
	{
		perror("open error");
		return 1;
	}
	int count = 5; // 准备写入5条
	const char* msg = "小帅真帅！\n";
	while (count--)
		write(fd, msg, strlen(msg));
	close(fd);
	return 0;
}
// 8. 读文件
int main()
{
	int fd = open("shuai.txt", O_RDONLY); // 存在文件了，调用两个参数的open
	if (fd < 0)
	{
		perror("open error");
		return 1;
	}
	char buff[1024];
	while (1)
	{
		ssize_t size = read(fd, buff, sizeof(buff));
		if (size > 0)
		{
			buff[size] = 0;
			printf("%s", buff);
		}
		else
			break;
	}
	close(fd);
	return 0;
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main()
{
	char buff[1024];
	int s = read(0, buff, sizeof(buff));
	if (s > 0)
	{
		buff[s] = 0;
		write(1, buff, strlen(buff));
		write(2, buff, strlen(buff));
	}
	return 0;
}
int main()
{
	int fd = open("hello.txt", O_RDONLY | O_CREAT);
	printf("%d\n", fd);
	return 0;
}
int main()
{
	close(1);
	open("hello.txt", O_WRONLY);
	const char* msg = "hello world!\n";
	int count = 5;
	while (count--)
		printf("%d:%s", count, msg);
	return 0;
}
int main()
{
	umask(0);
	int fd = open("log.txt", O_CREAT | O_RDWR, 0666);
	close(1); //  关闭标准输出，更好观察
	dup(fd, 1);
	for (;;)
	{
		char buff[1024];
		int size = read(0, buff, sizeof(buff) - 1);
		printf("%s", buff);
		fflush(stdout);
	}
	return 0;
}
struct file_operations {
	struct module* owner;
	//指向拥有该模块的指针； 
	loff_t(*llseek) (struct file*, loff_t, int);
	//llseek ⽅法⽤作改变⽂件中的当前读/写位置, 并且新位置作为(正的)返回值.  
	ssize_t(*read) (struct file*, char __user*, size_t, loff_t*);
	//⽤来从设备中获取数据. 在这个位置的⼀个空指针导致 read 系统调⽤以 -
	EINVAL("Invalid argument") 失败.⼀个⾮负返回值代表了成功读取的字节数(返回值是⼀个
		"signed size" 类型, 常常是⽬标平台本地的整数类型).
		ssize_t(*write) (struct file*, const char __user*, size_t, loff_t*);
	//发送数据给设备. 如果 NULL, -EINVAL 返回给调⽤ write 系统调⽤的程序. 如果⾮负, 返
	回值代表成功写的字节数.
		ssize_t(*aio_read) (struct kiocb*, const struct iovec*, unsigned long,
			loff_t);
	//初始化⼀个异步读 -- 可能在函数返回前不结束的读操作. 
	ssize_t(*aio_write) (struct kiocb*, const struct iovec*, unsigned long,
		loff_t);
	//初始化设备上的⼀个异步写. 
	int (*readdir) (struct file*, void*, filldir_t);
	//对于设备⽂件这个成员应当为 NULL; 它⽤来读取⽬录, 并且仅对**⽂件系统**有⽤. 
	unsigned int (*poll) (struct file*, struct poll_table_struct*);
	int (*ioctl) (struct inode*, struct file*, unsigned int, unsigned long);
	long (*unlocked_ioctl) (struct file*, unsigned int, unsigned long);
	long (*compat_ioctl) (struct file*, unsigned int, unsigned long);
	int (*mmap) (struct file*, struct vm_area_struct*);
	//mmap ⽤来请求将设备内存映射到进程的地址空间. 如果这个⽅法是 NULL, mmap 系统调⽤返
	回 - ENODEV.
		int (*open) (struct inode*, struct file*);
	//打开⼀个⽂件 
	int (*flush) (struct file*, fl_owner_t id);
	//flush 操作在进程关闭它的设备⽂件描述符的拷⻉时调⽤; 
	int (*release) (struct inode*, struct file*);
	//在⽂件结构被释放时引⽤这个操作. 如同 open, release 可以为 NULL. 
	int (*fsync) (struct file*, struct dentry*, int datasync);
	//⽤⼾调⽤来刷新任何挂着的数据. 
	int (*aio_fsync) (struct kiocb*, int datasync);
	int (*fasync) (int, struct file*, int);
	int (*lock) (struct file*, int, struct file_lock*);
	//lock ⽅法⽤来实现⽂件加锁; 加锁对常规⽂件是必不可少的特性, 但是设备驱动⼏乎从不实现
	它.
		ssize_t(*sendpage) (struct file*, struct page*, int, size_t, loff_t*,
			int);
	unsigned long (*get_unmapped_area)(struct file*, unsigned long, unsigned
		long, unsigned long, unsigned long);
	int (*check_flags)(int);
	int (*flock) (struct file*, int, struct file_lock*);
	ssize_t(*splice_write)(struct pipe_inode_info*, struct file*, loff_t*,
		size_t, unsigned int);
	ssize_t(*splice_read)(struct file*, loff_t*, struct pipe_inode_info*,
		size_t, unsigned int);
	int (*setlease)(struct file*, long, struct file_lock**);
};